package com.icepeach.icepeachhomeback.util;

import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.springframework.util.Assert;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * desc: 时间工具
 *
 * @author: 021835 xupz
 * @date 2020年12月8日 下午4:13:15
 */
public class DateUtil {
    /**
     * DASH破折号
     */
    public static final String DATE_FORMAT_DASH_TIME = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT_NO_DASH_TIME = "yyyyMMddHHmmss";

    /**
     * 日期格式静态字符串
     */
    public static final String YYYY = "yyyy";
    public static final String YYYY_MM = "yyyy-MM";
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    /**
     * 斜线格式的日期
     */
    public static final String DATE_FORMAT_SLASH = "yyyy/MM/dd";

    private static final String[] WEEK_DAYS = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    private static final String[] WEEK_DAYS_IN_CHINESE = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};


    /**
     * desc 在指定时间基础上加一段时间，如果是当前时间就传new Date
     * <p>
     * DateUtil.timeAddOrMinus(new Date(), Calendar.MINUTE, 10)
     * </p>
     *
     * @param baseDate
     * @param calendarType
     * @param num          void 加就是正数，减就是负数
     * @author: 021835 xupz
     * @date 2020年12月8日 下午4:15:37
     * @see Calendar
     */
    public static Date timeAddOrMinus(Date baseDate, int calendarType, int num) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(baseDate);
        calendar.add(calendarType, num);
        return calendar.getTime();
    }

    public static String getFullNowDateTime(String strDateFormat) {
        SimpleDateFormat ymd = new SimpleDateFormat(strDateFormat);
        return ymd.format(new Date());
    }

    /**
     * desc 平台标准时间格式，获取当前时间
     *
     * @return String
     * @author: 021835 xupz
     * @date 2020年12月9日 上午9:21:15
     */
    public static String getFullNowDateTime() {
        return getFullNowDateTime(DATE_FORMAT_DASH_TIME);
    }

    /**
     * 将时间转换为更直观的时间 比如将"2018-06-06 15:30:30"转换为"昨天 下午 3:30:30"
     *
     * @param dateString
     * @return
     * @author WangWeiWei 020463
     * @date 2018年7月5日 下午2:10:31
     */
    public static String getDirectViewTime(String dateString) throws Exception {
        Calendar calendar = Calendar.getInstance();
        Calendar currentCalendar = Calendar.getInstance();
        SimpleDateFormat daySfd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date currentDate = new Date();
        calendar.setTime(daySfd.parse(dateString));
        currentCalendar.setTime(currentDate);
        if (calendar.get(Calendar.YEAR) == currentCalendar.get(Calendar.YEAR)) {
            String dayDesc = "";
            int dayPassed = currentCalendar.get(Calendar.DAY_OF_YEAR) - calendar.get(Calendar.DAY_OF_YEAR);
            if (dayPassed == 0) {
                dayDesc = "今天";
            } else if (dayPassed == 1) {
                dayDesc = "昨天";
            } else if (dayPassed == 2) {
                dayDesc = "前天";
            } else if (dayPassed >= 3 && dayPassed <= 10) {
                dayDesc = NumUtils.translate(dayPassed) + "天前";
            } else if (dayPassed == -1) {
                dayDesc = "明天";
            } else if (dayPassed == -2) {
                dayDesc = "后天";
            } else if (dayPassed <= -3 && dayPassed >= -10) {
                dayDesc = NumUtils.translate(Math.abs(dayPassed)) + "天后";
            }
            if (!"".equals(dayDesc)) {
                if (calendar.get(Calendar.HOUR_OF_DAY) >= 0 && calendar.get(Calendar.HOUR_OF_DAY) < 6) {
                    return dayDesc + " 凌晨 " + new SimpleDateFormat("HH时mm分").format(daySfd.parse(dateString));
                } else if (calendar.get(Calendar.HOUR_OF_DAY) >= 6 && calendar.get(Calendar.HOUR_OF_DAY) < 9) {
                    return dayDesc + " 早晨 " + new SimpleDateFormat("HH时mm分").format(daySfd.parse(dateString));
                } else if (calendar.get(Calendar.HOUR_OF_DAY) >= 9 && calendar.get(Calendar.HOUR_OF_DAY) < 11) {
                    return dayDesc + " 上午 " + new SimpleDateFormat("HH时mm分").format(daySfd.parse(dateString));
                } else if (calendar.get(Calendar.HOUR_OF_DAY) >= 11 && calendar.get(Calendar.HOUR_OF_DAY) < 13) {
                    return dayDesc + " 中午 " + calendar.get(Calendar.HOUR_OF_DAY) + "时"
                            + new SimpleDateFormat("mm分").format(daySfd.parse(dateString));
                } else if (calendar.get(Calendar.HOUR_OF_DAY) >= 13 && calendar.get(Calendar.HOUR_OF_DAY) < 17) {
                    return dayDesc + " 下午 "
                            + ((calendar.get(Calendar.HOUR_OF_DAY) - 12) < 10
                            ? ("0" + (calendar.get(Calendar.HOUR_OF_DAY) - 12))
                            : (calendar.get(Calendar.HOUR_OF_DAY) - 12))
                            + "时" + new SimpleDateFormat("mm分").format(daySfd.parse(dateString));
                } else if (calendar.get(Calendar.HOUR_OF_DAY) >= 17 && calendar.get(Calendar.HOUR_OF_DAY) < 19) {
                    return dayDesc + " 黄昏 "
                            + ((calendar.get(Calendar.HOUR_OF_DAY) - 12) < 10
                            ? ("0" + (calendar.get(Calendar.HOUR_OF_DAY) - 12))
                            : (calendar.get(Calendar.HOUR_OF_DAY) - 12))
                            + "时" + new SimpleDateFormat("mm分").format(daySfd.parse(dateString));
                } else if (calendar.get(Calendar.HOUR_OF_DAY) >= 19 && calendar.get(Calendar.HOUR_OF_DAY) < 21) {
                    return dayDesc + " 晚上 "
                            + ((calendar.get(Calendar.HOUR_OF_DAY) - 12) < 10
                            ? ("0" + (calendar.get(Calendar.HOUR_OF_DAY) - 12))
                            : (calendar.get(Calendar.HOUR_OF_DAY) - 12))
                            + "时" + new SimpleDateFormat("mm分").format(daySfd.parse(dateString));
                } else if (calendar.get(Calendar.HOUR_OF_DAY) >= 21) {
                    return dayDesc + " 深夜 "
                            + ((calendar.get(Calendar.HOUR_OF_DAY) - 12) < 10
                            ? ("0" + (calendar.get(Calendar.HOUR_OF_DAY) - 12))
                            : (calendar.get(Calendar.HOUR_OF_DAY) - 12))
                            + "时" + new SimpleDateFormat("mm分").format(daySfd.parse(dateString));
                }
            }
        }
        return dateString;
    }

    /**
     * @param date          传入的date
     * @param strDateFormat 传入的date的格式
     * @return Date
     * @desc 将String类型的日期转化为date类型;
     * 该方法已过时，不建议使用。推荐调用parseStrToDate(String date,String format)或parseStrToDate(String date)
     */
    @Deprecated
    public static Date dateStringToDate(String date, String strDateFormat) throws ParseException {
        SimpleDateFormat df = new SimpleDateFormat(strDateFormat);
        return df.parse(date);
    }

    /**
     * desc 获取date类型的当前时间
     * 该方法已过时，不建议使用。推荐调用parseDateToStr(Date date);或parseDateToStr(Date date,String format);
     *
     * @return date
     * @author: 021835 xupz
     * @date 2020年12月9日 上午9:21:15
     */
    @Deprecated
    public static String getFormatDateTime(Date date) {
        try {
            SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT_DASH_TIME);
            return df.format(date);
        } catch (Exception e) {
            return getFullNowDateTime(DATE_FORMAT_DASH_TIME);
        }
    }

    /**
     * 传入一个时间的毫秒差值，转化为经历的时间，精确到分钟
     *
     * @param milliseconds
     * @return
     */
    public static String getDiffViewTime(long milliseconds) {
        long base = System.currentTimeMillis();
        DateTime start = new DateTime(base);
        DateTime end = new DateTime(base + milliseconds);
        Interval interval = new Interval(start, end);
        Period period = interval.toPeriod();
        return String.format("%d天%d小时%d分钟", period.getDays(), period.getHours(), period.getMinutes());
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 17:21
     * @description: 获取当前Date类型日期, 默认转换为标准的 YYYY_MM_DD_HH_MM_SS如Thu Jun 24 11:14:41 CST 2021转2021-06-24 11:15:05等格式(以输入的format为准)
     * @return: java.util.Date
     * @version: 1.0
     */
    public static String parseDateToStr(Date date) {
        return parseDateToStr(date, DATE_FORMAT_DASH_TIME);
    }

    /**
     * @param date:
     * @param format:
     * @author: 024910 Eden
     * @date: 2021/6/22 17:00
     * @description: 按指定格式format, 将Date类型转String，如Thu Jun 24 11:14:41 CST 2021转2021-06-24等格式(以输入的format为准)
     * @return: java.lang.String
     * @version: 1.0
     */
    public static String parseDateToStr(Date date, String format) {
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * @param format:
     * @param date:
     * @author: 024910 Eden
     * @date: 2021/6/22 16:59
     * @description: String类型转换为Date
     * @return: java.util.Date
     * @version: 1.0
     */
    public static Date parseStrToDate(String date, String format) throws ParseException {
        return new SimpleDateFormat(format).parse(date);
    }

    /**
     * @param date:
     * @author: 024910 Eden
     * @date: 2021/6/18 17:29
     * @description: 日期型字符串转化为日期格式, 如2021-06-24 11:14:41转Thu Jun 24 11:14:41 CST 2021
     * @return: java.util.Date
     * @version: 1.0
     */
    public static Date parseStrToDate(String date) throws ParseException {
        return parseStrToDate(date, DATE_FORMAT_DASH_TIME);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 17:31
     * @description: 获得当天是周几, 返回标准日期，如Fri代表周五
     * @return: java.lang.String
     * @version: 1.0
     */
    public static String getWeekDay() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) {
            w = 0;
        }
        return WEEK_DAYS[w];
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:04
     * @description: 获得当天是周几, 返回中文的星期几
     * @return: java.lang.String
     * @version: 1.0
     */
    public static String getWeekDayInChinese() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) {
            w = 0;
        }
        return WEEK_DAYS_IN_CHINESE[w];
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:24
     * @description: 获取当天是一年第几天
     * @return: int
     * @version: 1.0
     */
    public static int getDayOfYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DAY_OF_YEAR);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:25
     * @description: 获取当天是一年第几天
     * @return: int
     * @version: 1.0
     */
    public static int getDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:29
     * @description: 取得当月的最大日期
     * @return: int
     * @version: 1.0
     */
    public static int getMaxDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:30
     * @description: 取得当天为一年中的第几周
     * @return: int
     * @version: 1.0
     */
    public static int getWeekOfYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:30
     * @description: 取得当天为当月的第几周
     * @return: int
     * @version: 1.0
     */
    public static int getWeekOfMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.WEEK_OF_MONTH);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:42
     * @description: 获取当前月份
     * @return: int
     * @version: 1.0
     */
    public static int getMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:43
     * @description: 获取当天小时数，24小时制
     * @return: int
     * @version: 1.0
     */
    public static int getHour() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:43
     * @description: 获取当前小时的分数
     * @return: int
     * @version: 1.0
     */
    public static int getMinute() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MINUTE);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 18:43
     * @description: 获取当前分数的秒数
     * @return: int
     * @version: 1.0
     */
    public static int getSecond() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.SECOND);
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/18 17:30
     * @description: 获取服务器启动时间，获得时间格式为:Wed Jun 23 16:03:55 CST 2021
     * @return: java.util.Date
     * @version: 1.0
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * @param endDate:
     * @param nowDate:
     * @author: 024910 Eden
     * @date: 2021/6/18 17:30
     * @description: 计算两个Date类型的时间差
     * @return: java.lang.String, 返回结果如下，0天-23小时-59分钟-59秒
     * @version: 1.0
     */
    public static String getDateDifference(Date endDate, Date nowDate) {
        /** 获得两个时间的毫秒时间差异*/
        long diff = endDate.getTime() - nowDate.getTime();
        /** 计算差多少天*/
        long day = diff / MagicNumber.MILLS_OF_DAY;
        /**计算差多少小时*/
        long hour = diff % MagicNumber.MILLS_OF_DAY / MagicNumber.MILLS_OF_HOUR;
        /**计算差多少分钟*/
        long min = diff % MagicNumber.MILLS_OF_DAY % MagicNumber.MILLS_OF_HOUR / MagicNumber.MILLS_OF_MINTUE;
        /**计算差多少秒//输出结果*/
        long sec = diff % MagicNumber.MILLS_OF_DAY % MagicNumber.MILLS_OF_HOUR % MagicNumber.MILLS_OF_MINTUE / MagicNumber.MILLS_ONE_SECOND;
        /**输出结果*/
        return day + "天" + hour + "小时" + min + "分钟" + sec + "秒";
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/21 8:15
     * @description: 获取当前时间戳，为了统一其他语言的如php和unix系统获取的时间戳是10位长度的，精确到秒。
     * java时间戳长度是13位，精确到毫秒，选用13位。
     * @return: java.lang.String
     * @version: 1.0
     */
    public static String getTimeStamp() {
        return String.valueOf(System.currentTimeMillis());
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/21 8:22
     * @description: 获取指定格式时间
     * @return: java.lang.String
     * @version: 1.0
     */
    public static String getCurrentTime() {
        // 小写的hh取得12小时，大写的HH取的是24小时
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        return df.format(date);
    }

    /**
     * @param str:
     * @author: 024910 Eden
     * @date: 2021/6/21 8:33
     * @description: 转化为CST时间
     * @return: java.util.Date
     * @version: 1.0
     */
    public static Date CSTFormat(String str) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
        Date date = formatter.parse(str);
        return date;
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/21 8:45
     * @description: 获取当前日期是本年度第几周
     * @return: java.lang.String
     * @version: 1.0
     */
    public static String getSeqWeek() {
        Calendar c = Calendar.getInstance(Locale.CHINA);
        String week = Integer.toString(c.get(Calendar.WEEK_OF_YEAR));
        if (week.length() == 1) {
            week = "0" + week;
        }
        String year = Integer.toString(c.get(Calendar.YEAR));
        return year + "年第" + week + "周";
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/21 8:36
     * @description: 获取当前季度
     * @return: java.lang.Integer
     * @version: 1.0
     */
    public static Integer getCurrentSeason() {
        Calendar calendar = Calendar.getInstance();
        Integer month = calendar.get(Calendar.MONTH) + 1;
        int season = 0;
        if (month >= 1 && month <= 3) {
            season = 1;
        } else if (month >= 4 && month <= 6) {
            season = 2;
        } else if (month >= 7 && month <= 9) {
            season = 3;
        } else if (month >= 10 && month <= 12) {
            season = 4;
        }
        return season;
    }

    /**
     * @param year:
     * @author: 024910 Eden
     * @date: 2021/6/21 8:38
     * @description: 检测是否闰年
     * @return: boolean
     * @version: 1.0
     */
    public static boolean isLeapYear(int year) {
        if (year % 400 == 0) {
            return true;
        }
        if (year % 4 == 0) {
            return (year % 100 != 0);
        }
        return false;
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/21 8:46
     * @description: 获取当天开始时间, 0点0分0秒0毫秒开始
     * @return: java.util.Date
     * @version: 1.0
     */
    public static Date getDayBegin() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * @author: 024910 Eden
     * @date: 2021/6/21 8:46
     * @description: 获得当天结束时间，23时59分59秒59毫秒
     * @return: java.util.Date
     * @version: 1.0
     */
    public static Date getDayEnd() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 59);
        return cal.getTime();
    }

    /**
     * @param str:
     * @author: 024910 Eden
     * @date: 2021/6/21 8:56
     * @description: 返回美国时间格式
     * @return: java.lang.String
     * @version: 1.0
     */
    public static String getAmericanDate(String str) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        ParsePosition pos = new ParsePosition(0);
        Date strToDate = formatter.parse(str, pos);
        String j = strToDate.toString();
        String[] k = j.split(" ");
        return k[2] + k[1].toUpperCase() + k[5].substring(2, 4);
    }


    /**
     * 传入Date时间戳 ，转换成格式化的String类型时间
     * @param date
     * @return
     */
    public static String dateToStr(Date date) {
        Assert.notNull(date, "date is null");
        long time = date.getTime();
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()));
    }

    public static String dateToStr(Date date, String pattern) {
        Assert.notNull(date, "date is null");
        long time = date.getTime();
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern(pattern);
        return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()));
    }

    /**
     * 传入long时间戳 ，转换成格式化的String类型时间
     * @param time
     * @return
     */
    public static String timeOfLongToStr(long time) {
        Assert.notNull(time, "time is null");
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()));
    }
    public static String timeOfLongToStr(long time, String pattern) {
        Assert.notNull(time, "time is null");
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern(pattern);
        return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()));
    }

    /**
     * 传入String类型格式化时间，转换成Long类型的时间戳
     * @param strTime
     * @return
     */
    public static long timeOfStrToLong(String strTime){
        Assert.notNull(strTime, "time is null");
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parse = LocalDateTime.parse(strTime, ftf);
        return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public static long timeOfStrToLong(String strTime, String pattern){
        Assert.notNull(strTime, "time is null");
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern(pattern);
        LocalDateTime parse = LocalDateTime.parse(strTime, ftf);
        return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }
}
